package com.dingreading.cloud.ssxcx.service.impl;

import com.auth0.jwt.JWT;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.ssxcx.dto.MembersDto;
import com.dingreading.cloud.ssxcx.entity.*;
import com.dingreading.cloud.ssxcx.entity.table.XcxStudentLoginTableDef;
import com.dingreading.cloud.ssxcx.mapper.XcxStudentLoginMapper;
import com.dingreading.cloud.ssxcx.service.*;
import com.dingreading.cloud.ssxcx.util.jwt.JwtHelper;
import com.dingreading.cloud.ssxcx.util.redis.RedisService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * 小程序学生登录日志表 服务层实现。
 *
 * @author EDY
 * @since 2025-07-29
 */
@Service
public class XcxStudentLoginServiceImpl extends BaseServiceImpl<XcxStudentLoginMapper, XcxStudentLogin, XcxStudentLoginTableDef> implements XcxStudentLoginService {

    private static final String redisCodeKey = "xcx_pic_code_";
    private static final String TOKEN_HEADER_NAME = "XCX_TOKEN";
    private static final String LOGIN_TYPE_XCX_MOBILE = "XCX_MOBILE";
    private static final String REDIS_XCX_MOBILE_KEY = "ssxcx_mobile_login_";
    @Resource
    private MembersService membersService;
    @Resource
    private CmservicesService cmservicesService;
    @Resource
    private CmorderService cmorderService;
    @Resource
    private RedisService redisService;

    @Override
    protected XcxStudentLoginTableDef getTable() {
        return XcxStudentLoginTableDef.xcxStudentLogin;
    }

    @Override
    public void getPicCode(HttpServletResponse response, String timestamp) throws IOException {
        // 设置响应的类型格式为图片格式
        response.setContentType("image/jpeg");
        // 禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        //实例生成验证码对象
        SCaptcha instance = new SCaptcha();
        String code = instance.getCode();
        if (StringUtils.isNotBlank(code)) {
            //将验证码存入redis
            redisService.set(redisCodeKey + timestamp, code, 120);
            //向页面输出验证码图片
            instance.write(response.getOutputStream());
        }
    }

    @Override
    public R<Object> getStudentInfo(HttpServletRequest request) {
        String token = getCookie(request.getCookies());
        if (StringUtils.isBlank(token))
            return R.fail("未发现令牌，请重新登录");

        // 获取token中的员工uid并查处员工信息
        String decodeToken = JWT.decode(token).getAudience().get(0);
        if (StringUtils.isBlank(decodeToken))
            return R.fail("解析令牌失败");

        // 新版验证
        String[] tokens = StringUtils.split(decodeToken, "-");
        String studentUid = tokens[0];
        String agencyUid = tokens[1];

        if (StringUtils.isBlank(studentUid) || StringUtils.isBlank(agencyUid))
            return R.fail("解析令牌的参数为空");

        MembersDto members = membersService.getByUid(studentUid);
        if (members == null) {
            return R.fail("用户不存在");
        }
        members.setAgencyUid(members.getCorpUid());
        members.setNickname(members.getMemberName());
        members.setTelephone(members.getMob());

        List<Cmservices> cmservices = cmservicesService.getByStudentUid(members.getUid());
        if (CollectionUtils.isEmpty(cmservices)) {
            return R.fail("用户未添加双思课程");
        }

        return R.ok(members);
    }

    @Override
    public R<Object> studentLogin(HttpServletRequest request, String uid, String password, String timestamp, String code) throws ParseException {
        if (StringUtils.isBlank(uid))
            return R.fail("请填写学生uid");
        if (StringUtils.isBlank(password))
            return R.fail("请填写登录密码");
        if (StringUtils.isBlank(code))
            return R.fail("请填写验证码");
        if (StringUtils.isBlank(timestamp))
            return R.fail("未传递时间戳");

        // 验证验证码
        String redisKey = redisCodeKey + timestamp;
        String redisPicCode = redisService.getValue(redisKey);
        redisService.delete(redisKey);
        if (StringUtils.isBlank(redisPicCode)) {
            return R.fail("验证码已失效");
        } else {
            String upperSessionCode = redisPicCode.toUpperCase();
            String upperCode = code.toUpperCase();
            if (!upperSessionCode.equals(upperCode)) {
                return R.fail("验证码错误");
            }
        }

        MembersDto members = membersService.getByUid(uid);
        if (members == null) {
            return R.fail("用户不存在");
        }
        members.setAgencyUid(members.getCorpUid());
        members.setNickname(members.getMemberName());
        members.setTelephone(members.getMob());
        // 判断密码是否正确
        String md5Password = MD5Util.MD5Encode(password, "UTF-8");
        if (!md5Password.equals(members.getPassword())) {
            return R.fail("请输入正确密码");
        }

        List<Cmservices> cmservicesList = cmservicesService.getByStudentUid(members.getUid());
        if (CollectionUtils.isEmpty(cmservicesList))
            return R.fail("用户未添加双思课程");

        double totalActivateAmount = 0d;
        for (Cmservices cmservices : cmservicesList) {
            totalActivateAmount += NepUtil.nullToZero(cmservices.getActivateAmount());
        }
        if (totalActivateAmount <= 0)
            return R.fail("用户未添加双思课程");

        // 添加登录记录
        String ipAddr = IpUtil.getIpAddr(request);
        String token = saveLoginLog(members, ipAddr);
        members.setToken(token);

        // 清空上次登录的缓存信息
        redisService.delete(REDIS_XCX_MOBILE_KEY + members.getUid() + "-" + members.getCorpUid());

        return R.ok(members);
    }

    @Override
    public R<Object> logout(String agencyUid, String uid) {
        // 清空上次登录的缓存信息
        redisService.delete(REDIS_XCX_MOBILE_KEY + uid + "-" + agencyUid);
        return R.ok();
    }

    @Override
    public R<Object> mdyPassword(String agencyUid, String uid, String newPass, String confirmPass) {
        Members members = membersService.getByUids(uid);
        if (members == null) {
            return R.fail("用户不存在");
        }
        if (newPass.length() < 6 || newPass.length() > 16)
            return R.fail("新密码长度应在6-16位");
        if (!newPass.equals(confirmPass))
            return R.fail("两次输入的新密码不一样");

        String md5Password = MD5Util.MD5Encode(newPass, "UTF-8");
        members.setPassword(md5Password);
        members.setLastStaffUid(members.getUid());
        members.setLastStaffName(members.getMemberName());

        boolean b = membersService.updateById(members);
        if (!b)
            return R.fail("密码修改失败");

        return R.ok();
    }

    /**
     * 添加登录记录
     *
     * @return
     */
    private String saveLoginLog(MembersDto student, String ipAddr) throws ParseException {
        XcxStudentLogin xcxStudentLogin = new XcxStudentLogin();
        xcxStudentLogin.setAgencyUid(student.getCorpUid());
        xcxStudentLogin.setStoreUid(student.getStoreUid());
        String loginTime = DateUtil.getNowDatetimeStr();
        xcxStudentLogin.setLoginTime(loginTime);
        xcxStudentLogin.setStudentUid(student.getUid());
        xcxStudentLogin.setNickname(student.getMemberName());
        xcxStudentLogin.setPhone(student.getMob());
        xcxStudentLogin.setIp(ipAddr);
        xcxStudentLogin.setDevice(LOGIN_TYPE_XCX_MOBILE);

        String token = JwtHelper.getToken(student.getUid(), student.getCorpUid(), loginTime);
        xcxStudentLogin.setToken(token);

        Date twoDayTime = DateUtil.addDays(DateUtil.getNowDatetime(), 2);
        String expireTime = DateUtil.getDefaultLastTimeStr(twoDayTime);
        Date date = DateUtil.parseDateFromStr(expireTime);
        xcxStudentLogin.setExpireTime(date);

        save(xcxStudentLogin);

        return token;
    }

    /**
     * 获取cookie信息
     */
    private String getCookie(Cookie[] cookies) {
        String cookieName = TOKEN_HEADER_NAME;
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookieName.equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }
        return "";
    }
}
